#include "ebnf2bnf.h"
#include <iostream>

Ebnf2BnfConverter::Ebnf2BnfConverter() : nextNt_(1000) {}  // 从 1000 偶数开始生成

void Ebnf2BnfConverter::setGrammar(const GrammarEBNF& ebnf) {
    ebnf_ = ebnf;
    bnf_.clear();
}

const Ebnf2BnfConverter::GrammarBNF& Ebnf2BnfConverter::getBnfGrammar() const {
    return bnf_;
}

int Ebnf2BnfConverter::genNonTerminal() {
    int nt = nextNt_;
    nextNt_ += 2;
    return nt;
}

std::vector<std::vector<int>> Ebnf2BnfConverter::splitAlternatives(const std::vector<int>& seq) {
    std::vector<std::vector<int>> alts;
    std::vector<int> cur;

    for (int tok : seq) {
        if (tok == -5) {  // '|' 分隔符
            alts.push_back(cur);
            cur.clear();
        }
        else {
            cur.push_back(tok);
        }
    }
    alts.push_back(cur);
    return alts;
}

void Ebnf2BnfConverter::processRule(int lhs, const std::vector<int>& rhs) {
    std::vector<int> newRhs;
    size_t i = 0, n = rhs.size();

    while (i < n) {
        int tok = rhs[i];

        // 处理括号结构 '(' ... [*+?]
        if (tok == -1) {  // '('
            size_t j = i + 1;
            while (j < n && rhs[j] != -2) ++j;  // 寻找匹配的 ')'
            if (j >= n) throw std::invalid_argument("Unmatched '('.");

            std::vector<int> inner(rhs.begin() + i + 1, rhs.begin() + j);
            char quant = 0;
            if (j + 1 < n && (rhs[j + 1] == -3 || rhs[j + 1] == -4 || rhs[j + 1] == -6)) {
                quant = static_cast<char>(rhs[j + 1]);
                j++;
            }

            auto alts = splitAlternatives(inner);

            if (quant == 0 && alts.size() == 1) {
                // 无量化的单序列，直接内联
                newRhs.insert(newRhs.end(), alts[0].begin(), alts[0].end());
            }
            else {
                int G = genNonTerminal();
                std::vector<std::vector<int>> rules;

                if (quant == -6) {  // '?'
                    rules.reserve(alts.size() + 1);
                    for (auto& seq_alt : alts) rules.push_back(seq_alt);
                    rules.push_back({ 0 });  // ε
                }
                else if (quant == -3) {  // '*'
                    rules.reserve(alts.size() + 1);
                    for (auto& seq_alt : alts) {
                        std::vector<int> s = seq_alt;
                        s.push_back(G);
                        rules.push_back(s);
                    }
                    rules.push_back({ 0 });
                }
                else if (quant == -4) {  // '+'
                    rules.reserve(alts.size() * 2);
                    for (auto& seq_alt : alts) {
                        std::vector<int> s = seq_alt;
                        s.push_back(G);
                        rules.push_back(s);
                    }
                    for (auto& seq_alt : alts) rules.push_back(seq_alt);
                }
                else if (alts.size() > 1) {  // 纯交替
                    rules.assign(alts.begin(), alts.end());
                }

                bnf_[G] = rules;
                newRhs.push_back(G);
            }

            i = j + 1;
        }
        // 处理带量词的单个符号
        else if (tok > 0 && i + 1 < n &&
            (rhs[i + 1] == -3 || rhs[i + 1] == -4 || rhs[i + 1] == -6)) {
            int symbol = tok;
            char quant = static_cast<char>(rhs[i + 1]);
            int G = genNonTerminal();

            std::vector<std::vector<int>> rules;
            if (quant == -6) {  // '?'
                rules = { {symbol}, {0} };
            }
            else if (quant == -3) {  // '*'
                rules = { {symbol, G}, {0} };
            }
            else if (quant == -4) {  // '+'
                rules = { {symbol, G}, {symbol} };
            }

            bnf_[G] = rules;
            newRhs.push_back(G);
            i += 2;
        }
        // 普通符号或 ε
        else {
            newRhs.push_back(tok);
            i++;
        }
    }

    bnf_[lhs].push_back(newRhs);
}

void Ebnf2BnfConverter::convert() {
    for (auto& pr : ebnf_) {
        processRule(pr.first, pr.second);
    }
}
